/*!
 * Copyright (c) 2010 Jacob Essex
 *
 * Dual licenced under MIT or GPL 3 licneces
 * 
 * See the GPL3 or MIT files in the main directory for details
 */

require.def('chain', [], function(){

    function popFunctions(curChain, successFunc, errorFunc){
        if ( curChain.length === 0 ){
            successFunc();
            return;
        }
        var cur = curChain.pop();

        var funcArgs = {error:errorFunc};
        funcArgs[cur.expectedType] = function(arg){
            if ( cur.expected === undefined ){
                popFunctions(curChain, successFunc, errorFunc);
            }else if ( typeof(cur.expected) === 'function' ){
                if ( cur.expected.apply(null, arguments) ){
                    popFunctions(curChain, successFunc, errorFunc);
                }
            }else if ( arg === cur.expected ){
                popFunctions(curChain, successFunc, errorFunc);
            }
        }
        cur.args.push(funcArgs);
        cur.func.apply(null, cur.args);
    }

    return {
        create: function(){
            var functionChain = [];
            var errorFunc = function(){};
            var successFunc = function(){};
            return {
                /**
                 * Does the work and executes all the queued functions. This flushes the queue
                 */
                exec:function(){
                    functionChain.reverse();
                    popFunctions(functionChain, successFunc, errorFunc);
                },
                /**
                 * sets the function that is called for all functons on an error
                 *
                 * @param func a callback when an error occures
                 */
                error:function(func){
                    errorFunc = func;
                    return this;
                },
                success:function(f){
                    successFunc = f;
                    return this;
                },
                queue:function(func, args, expectedType, expectedValue){
                    functionChain.push({
                        'func':func,
                        'args':args,
                        'expectedType':expectedType,
                        'expected':expectedValue
                    });
                    return this;
                }
            }
        }
    };

});
